package com.bolun998300.personal_blog_springboot.service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;

import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.highlight.HighlightBuilder;
import org.elasticsearch.search.highlight.HighlightField;
import org.elasticsearch.search.sort.ScoreSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;

import com.bolun998300.personal_blog_springboot.dao.BlogDao;
import com.bolun998300.personal_blog_springboot.dao.Blog_TagDao;
import com.bolun998300.personal_blog_springboot.es.BlogEsDao;
import com.bolun998300.personal_blog_springboot.pojo.Blog;
import com.bolun998300.personal_blog_springboot.pojo.Blog_Tag;

@Service
public class BlogService {

    String preTag = "<font color='#dd4b39'>";//google的色值
    String postTag = "</font>";

    @Autowired
    private BlogDao blogDao;
    @Autowired
    private BlogEsDao blogEsDao;
    @Autowired
    private Blog_TagDao blogTagDao;

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;


    public List<Blog> list(){
        return  blogDao.findByIsDeleteOrderByCreateTimeDesc(false);
    }

    public List<Blog> findByIsDeleteAndNewsTopOrderByCreateTimeDesc(){
        return blogDao.findByIsDeleteAndNewsTopAndNewsStatusOrderByCreateTimeDesc(false,true,1);
    }

    public Page<Blog> listByPage(int page,int size,boolean isDelete){
        Sort sort = new Sort(Sort.Direction.DESC,"id");
        Pageable pageable = new PageRequest(page-1,size,sort);
        Page<Blog> pageFromJPA = blogDao.findByIsDeleteOrderByCreateTimeDesc(isDelete,pageable);
        return pageFromJPA;
    }

    public Page<Blog> listByPageNoTop(int page,int size){
        Sort sort = new Sort(Sort.Direction.DESC,"id");
        Pageable pageable = new PageRequest(page-1,size,sort);
        Page<Blog> pageFromJPA = blogDao.findByIsDeleteAndNewsTopAndNewsStatusOrderByCreateTimeDesc(false,false,pageable,1);
        return pageFromJPA;
    }
    
    public Page<Blog> listByPageAndTypeID(int page,int size,int typeId){
    	Sort sort = new Sort(Sort.DEFAULT_DIRECTION.DESC,"id");
    	Pageable pageable = new PageRequest(page-1,size,sort);
    	Page<Blog> pageFromJPA = blogDao.findByIsDeleteAndTypeIdAndNewsStatus(false, typeId, pageable,1);
    	return pageFromJPA;
    }
    
    public Page<Blog> findByIsDeleteOrderByClickHitDesc(){
    	Sort sort = new Sort(Sort.Direction.DESC,"clickHit");
        Pageable pageable = new PageRequest(0,5,sort);
        Page<Blog> pageFromJPA = blogDao.findByIsDeleteOrderByClickHitDesc(false, pageable);
        return pageFromJPA;
    }
    
    public Page<Blog> getBlogByPageDeleted(int page,int size){
    	Sort sort = new Sort(Sort.DEFAULT_DIRECTION.DESC,"id");
    	Pageable pageable = new PageRequest(page-1,size,sort);
    	Page<Blog> pageFromJPA = blogDao.findByIsDeleteOrderByCreateTimeDesc(true,pageable);
    	return pageFromJPA;
    }
    
    public Page<Blog> getDraftBlogByPage(int page,int size){
    	Sort sort = new Sort(Sort.DEFAULT_DIRECTION.DESC,"id");
    	Pageable pageable = new PageRequest(page-1,size,sort);
    	Page<Blog> pageFromJPA = blogDao.findByIsDeleteAndNewsStatusOrderByCreateTimeDesc(false, 0, pageable);
    	return pageFromJPA;
    }


	public Page<Blog> listByPageAndTagId(int page, int limit, int tagId) {
		List<Blog_Tag> blogTagList = blogTagDao.findByTagId(tagId);
		int[] blogIdArr = new int[blogTagList.size()];
		int i = 0;
		for(Blog_Tag blogTag : blogTagList) {
			blogIdArr[i] = blogTag.getBlogId();
			i++;
		}
		Sort sort = new Sort(Sort.DEFAULT_DIRECTION.DESC,"id");
		Pageable pageable = new PageRequest(page-1,limit,sort);
		Page<Blog> pageFromJPA = blogDao.findByIsDeleteAndNewsStatusAndIdInOrderByCreateTimeDesc(false, 1, blogIdArr,pageable);
    	return pageFromJPA;
	}
    

    
    
    public Blog get(int id){
        return blogDao.findOne(id);
    }

    public void update(Blog bean){
        blogDao.save(bean);
        blogEsDao.save(bean);
    }

    public void save(Blog bean){
        blogDao.save(bean);
        blogEsDao.save(bean);
    }

    public void delete(int id){
        blogDao.delete(id);
        blogEsDao.delete(id);
    }


    private void initDatebase2ES(){
        Pageable pageable = new PageRequest(0,5);
        Page<Blog> page = blogEsDao.findAll(pageable);
        if(page.getContent().isEmpty()){
            List<Blog> blogs2= blogDao.findAll();
            blogEsDao.save(blogs2);
        }
    }


    public Page<Blog> searchByName(int page,int size,String keyWord){
        initDatebase2ES();
        FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery()
                .add(QueryBuilders.matchPhraseQuery("title", keyWord),
                        ScoreFunctionBuilders.weightFactorFunction(100))
                .scoreMode("sum")
                .setMinScore(10);
        Sort sort  = new Sort(Sort.Direction.DESC,"id");
        Pageable pageable = new PageRequest(page-1,size,sort);
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withPageable(pageable)
                .withQuery(functionScoreQueryBuilder).build();
    //    Page<Blog> blogPage = blogEsDao.findByIsDeleteOrderByCreateTimeDesc(false,pageable,searchQuery);
        Page<Blog> blogPage = blogEsDao.search(searchQuery);
        return  blogPage;
    }

    public Page<Blog> getBlogByPageAndSearchWord(int page,int size,String keyWord){
        initDatebase2ES();

        FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery()
                .add(QueryBuilders.matchPhraseQuery("title", keyWord),
                        ScoreFunctionBuilders.weightFactorFunction(100))
                .add(QueryBuilders.matchPhraseQuery("content", keyWord),
                        ScoreFunctionBuilders.weightFactorFunction(100))
                .scoreMode("sum")
                .setMinScore(10);

//        NativeSearchQuery nativeSearchQuery=new NativeSearchQueryBuilder()
//                .withQuery(functionScoreQueryBuilder)
//                .withHighlightFields(new HighlightBuilder.Field("content"),new HighlightBuilder.Field("name"))
//                .withHighlightBuilder(new HighlightBuilder().preTags("<span style='color:red'>").postTags("</span>")).build();


        Sort sort  = new Sort(Sort.Direction.DESC,"id");
        Pageable pageable = new PageRequest(page-1,size,sort);
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withPageable(pageable)
                .withQuery(functionScoreQueryBuilder)
                .withHighlightFields(new HighlightBuilder.Field("content").preTags(preTag).postTags(postTag)
                        ,new HighlightBuilder.Field("title").preTags(preTag).postTags(postTag))

                .build();
        //    Page<Blog> blogPage = blogEsDao.findByIsDeleteOrderByCreateTimeDesc(false,pageable,searchQuery);
        Page<Blog> blogPage = blogEsDao.search(searchQuery);


//        AggregatedPage<Blog> blogPage = elasticsearchTemplate.queryForPage(searchQuery, Blog.class, new SearchResultMapper() {
//            @Override
//            public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
//                List<Blog> blogs = new ArrayList<>();
//                for(SearchHit searchHit : response.getHits()){
//                    if(response.getHits().getHits().length<=0){
//                        return null;
//                    }
//                    Blog blog = new Blog();
//
//                    HighlightField blogTitle = searchHit.getHighlightFields().get("title");
//                    if(blogTitle != null){
//                        blog.setTitle(blogTitle.fragments()[0].toString());
//                    }
//                    HighlightField blogContent = searchHit.getHighlightFields().get("content");
//                    if(blogContent != null){
//                        blog.setContent(blogContent.fragments()[0].toString());
//                    }
//
//                    blogs.add(blog);
//                }
//                if (blogs.size() > 0) {
//                    return new AggregatedPageImpl<>((List<T>) blogs);
//                }
//
//
//                return null;
//            }
//        });



        return  blogPage;

    }



}
